/* === LICENSE INFO ===
 * This source file is subject to the GPLv3 license that is bundled with this
 * package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.gnu.org/licenses/gpl.txt
 * === end of LICENSE INFO === */

/*==============================================================================
  File Name   : GDateTime.cpp
  Description : Definition for GDateTime module of gUtil.

  Created on  : 2009-11-04
  Updated on  : 2011-01-30
  Updated by  : Lee Shiou Ming

  Cautions    : (important notes)
  ============================================================================*/

//------------------------------------------------------------------------------
//-- INCLUDES & DEFINES
//------------------------------------------------------------------------------
#include "GDateTime.hpp"

using namespace gUtil;
using namespace boost;


//------------------------------------------------------------------------------
//-- INITIALIZATIONS
//------------------------------------------------------------------------------


//------------------------------------------------------------------------------
//-- FUNCTION IMPLEMENTATIONS
//------------------------------------------------------------------------------
posix_time::ptime GDateTime::getCurrentTime()
{
    posix_time::ptime now(posix_time::microsec_clock::local_time());
    return now;
}


std::string GDateTime::getDateTimeString(
        const ptime& _now,
        TimePrecision _precision)
{
    using namespace boost::local_time;

    std::stringstream stream;
    std::string dateTimeString;

    time_zone_ptr timezoneGMT(new posix_time_zone("GMT"));
    local_date_time localDateTime(_now, timezoneGMT);

    local_time_facet *outputFacet = new local_time_facet();
    local_time_input_facet *inputFacet = new local_time_input_facet();
    stream.imbue(std::locale(std::locale::classic(), outputFacet));
    stream.imbue(std::locale(stream.getloc(), inputFacet));

    if (_precision == PRECISION_SECOND)
    {
        outputFacet->format("%Y-%m-%d %H:%M:%S");
    }
    else
    {
        // %f = fixed 6-digits microsecond
        outputFacet->format("%Y-%m-%d %H:%M:%S.%f");
    }

    stream.str("");
    stream << localDateTime;
    dateTimeString = stream.str();
    if (_precision == PRECISION_MILLESECOND)
    {
        // Millisecond precision = microsecond precision strips 3 digits
        dateTimeString = dateTimeString.substr(0, dateTimeString.length() - 3);
    }

    return dateTimeString;
}


std::string GDateTime::getDateTimeString(TimePrecision _precision)
{
    posix_time::ptime now = GDateTime::getCurrentTime();

    return getDateTimeString(now, _precision);
}


std::string GDateTime::getDateString(const ptime& _now, bool _isDelimited)
{
    using namespace boost::gregorian;

    date today(_now.date());
    std::string dateString;

    if (_isDelimited)
    {
        dateString = to_iso_extended_string(today);
    }
    else
    {
        dateString = to_iso_string(today);
    }

    return dateString;
}


std::string GDateTime::getDateString(bool _isDelimited)
{
    posix_time::ptime now = GDateTime::getCurrentTime();

    return getDateString(now, _isDelimited);
}


std::string GDateTime::getTimeString(
        const ptime& _now,
        TimePrecision _precision,
        bool _isDelimited)
{
    using namespace boost::posix_time;

    std::stringstream stream;

    time_facet* outputFacet = NULL;
    if (_precision == PRECISION_SECOND)
    {
        if (_isDelimited) outputFacet = new time_facet("%H:%M:%S");
        else              outputFacet = new time_facet("%H%M%S");
    }
    else
    {
        // %f = fixed 6-digits microsecond
        if (_isDelimited) outputFacet = new time_facet("%H:%M:%S.%f");
        else              outputFacet = new time_facet("%H%M%S.%f");
    }

    stream.imbue(std::locale(stream.getloc(), outputFacet));
    stream.str("");
    stream << _now;

    std::string timeString = stream.str();
    if (_precision == PRECISION_MILLESECOND)
    {
        // Millisecond precision = microsecond precision strips 3 digits
        timeString = timeString.substr(0, timeString.length() - 3);
    }

    return timeString;
}


std::string GDateTime::getTimeString(TimePrecision _precision, bool _isDelimited)
{
    posix_time::ptime now = GDateTime::getCurrentTime();

    return getTimeString(now, _precision, _isDelimited);
}
